<script setup lang="ts">
import { computed, h, onMounted, reactive, ref } from 'vue';
import { NInput, NButton, NSpace, NForm, NFormItem, FormRules, NDataTable, DataTableColumns, useMessage, NP, NText, NH2, FormInst } from 'naive-ui';
import { getCheckedCart } from '../util/cart';
import { queryGoodsInfo } from '../api/goods';
import statusCode from '../api/statusCode';
import { createOrder, OrderInfo } from '../api/order';
import { CartItem } from '../store';
import { handleNoToken, listAllError } from '../util/handler';
import { getToken } from '../util/token';
import router from '../router';

const message = useMessage();

const cartItems = getCheckedCart();

const formValue = reactive({
  address: '',
  name: '',
  phone: ''
});

const rules: FormRules = {
  address: {
    trigger: ['input', 'blur'],
    message: '请输入收货地址',
    required: true
  },
  name: {
    trigger: ['input', 'blur'],
    message: '请输入收货人姓名',
    required: true
  },
  phone: {
    trigger: ['input', 'blur'],
    message: '请输入手机号',
    required: true
  },
};

type TableItem = { storeId: number; storeName: string; productId: number; productName: string; attributeId: number; unitPrice: number; quantity: number; color: string; stock: number; }
const tableItems = reactive<TableItem[]>([]);

const loading = ref(false);
const getCart = () => {
  loading.value = true;

  tableItems.length = 0;
  const promises = [] as ReturnType<typeof getGoodsInfo>[];
  cartItems.forEach(i => {
    const p = getGoodsInfo(i.productId);
      p
      .then(info => {
        if (info) {
          const attr = info.info.find(attr => attr.attributeId == i.attributeId);
          if (!attr) throw new Error(`无法找到id为${info.productId}的属性${i.attributeId}`);
          tableItems.push({
            storeId: info.storeId,
            storeName: info.storeName,
            productId: info.productId,
            productName: info.productName,
            attributeId: attr.attributeId,
            color: attr.color,
            unitPrice: attr.unitPrice,
            quantity: i.quantity,
            stock: attr.stock
          });
        }
      })
      .catch(err => message.error('' + err));
    promises.push(p);
  });
  Promise.allSettled(promises)
  .then(() => {
    loading.value = false;
    tableItems.sort((a, b) => a.attributeId - b.attributeId);
  });
};

const getGoodsInfo = async (productId: number) => {
  try {
    const resp = await queryGoodsInfo(productId);
    if (resp.status === statusCode.SUCCESS) {
      return resp.data;
    } else {
      throw new Error(`查找id为${productId}的产品信息时出错`);
    }
  } catch (error) {
    message.error('' + error);
    return null;
  }
};

const columns: DataTableColumns<TableItem> = [
  {
    title: '商店',
    key: 'storeName'
  },
  {
    title: '商品',
    key: 'productName'
  },
  {
    title: '颜色',
    key: 'color'
  },
  {
    title: '单价',
    key: 'unitPrice',
    render(row) {
      return h('span', {}, { default: () => '￥' + row.unitPrice });
    }
  },
  {
    className: 'quantity-row',
    title: '数量',
    key: 'quantity'
  },
  {
    title: '小计',
    key: 'total',
    render(row) {
      return h('span', { className: 'price' }, { default: () => (row.unitPrice * row.quantity).toFixed(2) });
    }
  },
  {
    title: '状态',
    key: 'status',
    render(row) {
      return h('span', {}, { default: () => row.stock > 0 ? '有货' : '无货' });
    }
  },
];

onMounted(getCart);

const totalPrice =
  computed(() =>
    tableItems
    .reduce(
      (accumulateVal, item) =>
        accumulateVal + (item.unitPrice * item.quantity),
        0
    )
    .toFixed(2)
  );

const addressInfo =
  computed(() =>
    `${formValue.address} ${formValue.name} ${formValue.phone}`
  );

const createOrderReq = (items: CartItem[]) => {
  const storeIds = new Set(items.map(i => i.storeId));
  
  const m = new Map<OrderInfo['storeId'], OrderInfo['info']>();
  storeIds.forEach(id => m.set(id, []));

  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
  items.forEach(i => m.get(i.storeId)!.push({
    productId: i.productId,
    attributeId: i.attributeId,
    goodQuantity: i.quantity
  }));

  const address = `${formValue.address} ${formValue.name} ${formValue.phone}`;
  const req: OrderInfo[] = [];
  for (const [id, infos] of m) req.push({ storeId: id, address, info: infos });

  return req;
};

const formRef = ref<FormInst | null>(null);
const formValidate = async () => {
  return await formRef.value?.validate();
};

const handleBtnClick = async () => {
  try {
    await formValidate();

    const req = createOrderReq(cartItems);
    const token = getToken();
    if (!token) {
      handleNoToken(message);
      return;
    }

    try {
      const resp = await createOrder({
        orderInfos: req,
        token
      });

      if (resp.status === statusCode.SUCCESS) {
        message.success('下单成功', {
          duration: 1200,
          onAfterLeave: () => router.replace({ name: 'orderSuccess' })
        });
      } else {
        throw new Error(`错误码 ${resp.status}`);
      }
    } catch (error) {
      message.error("" + error);
    }

  } catch (errors) {
    if (errors instanceof Array) {
      listAllError(errors, message);
    } else {
      throw errors;
    }
  }

};
</script>

<template>
  <n-space
    vertical
  >
    <n-h2 prefix="bar">
      订单信息
    </n-h2>
    <n-form
      inline
      ref="formRef"
      :model="formValue"
      :rules="rules"
    >
      <n-space>
        <n-form-item
          label="收货地址"
          path="address"
        >
          <n-input
            v-model:value="formValue.address"
            type="text"
            placeholder="收货地址"
          />
        </n-form-item>

        <n-form-item
          label="收货人姓名"
          path="name"
        >
          <n-input
            v-model:value="formValue.name"
            type="text"
            placeholder="姓名"
          />
        </n-form-item>
    
        <n-form-item
          label="手机号码"
          path="phone"
        >
          <n-input
            v-model:value="formValue.phone"
            type="text"
            placeholder="手机号码"
          />
        </n-form-item>
      </n-space>
    </n-form>

    <n-h2 prefix="bar">
      确认商品
    </n-h2>
    <n-data-table
      :columns="columns"
      :data="tableItems"
    />

    <n-space
      align="center"
      justify="end"
    >
      <n-p>
        寄送至：
        <n-text
          class="address-info"
          depth="2"
        >
          {{ addressInfo }}
        </n-text>
      </n-p>
      <n-p>
        总价：
        <n-text
          class="total-price price"
          type="error" 
          depth="1"
          strong
        >
          {{ totalPrice }}
        </n-text>
      </n-p>
    </n-space>
    <div class="dummy">
      <n-button
        class="push"
        type="primary"
        :disabled="cartItems.length == 0"
        @click="handleBtnClick"
      >
        立即下单
      </n-button>
    </div>
  </n-space>
</template>

<style scoped>
::v-deep(.price::before) {
  content: "￥";
}
::v-deep(.price) {
  color: rgb(232, 59, 51);
  font-weight: bolder;
}
.total-price {
  font-size: 24px;
}
.dummy {
  display: flex;
}
.push {
  margin-left: auto;
}
</style>
